from typing import List

from langchain_openai.chat_models.base import BaseChatOpenAI
from redis import Redis

from .nodes.mcp import MCPNodes
from ..graph.base import BaseGraph
from ..graph.nodes import *
from ..llms import LLMConfig, create_openai_llm
from ..mcps import MCPClientManager
from ..parser.xml_parser import XmlToolResultParser


class CoderGraph(BaseGraph):
    """
    专业的软件工程师AI助手。
    拥有丰富的编程语言、框架、设计模式和最佳实践知识，能够帮助用户完成各种软件开发任务。
    可以使用多种工具来分析代码、修改文件、执行命令、搜索信息等，以逐步完成用户的开发需求。
    系统会根据用户输入的问题自动分析并设置以下参数：
    - title (必选): 基于用户问题生成的标题，能概括问题的核心内容或意图，控制在20个字以内。
    """
    llm_vl: BaseChatOpenAI = None
    llm_image: BaseChatOpenAI = None

    def __init__(self,
                 llm_vl: BaseChatOpenAI | LLMConfig,
                 llm_image: BaseChatOpenAI | LLMConfig,
                 redis: Redis = None,
                 nodes: List[BaseNodes] = [],
                 agent_template: str = "agent_coder",
                 mcp_client: MCPClientManager = None,
                 **kwargs):
        super().__init__(graph_name="agent_coder_",
                         agent_template=agent_template,
                         redis=redis,
                         mcp_client=mcp_client,
                         **kwargs)
        nodes = nodes if nodes else []
        self.llm_vl = create_openai_llm(llm_vl) if isinstance(llm_vl, LLMConfig) else llm_vl
        self.llm_image = create_openai_llm(llm_image) if isinstance(llm_image, LLMConfig) else llm_image
        self.nodes = nodes if nodes else [AskUserNodes(), CommandNodes(), CompletionNodes(), FileNodes(), WebNodes(),
                                          ImageNodes(llm_vl=self.llm_vl, llm_image=self.llm_image)]
        if mcp_client and mcp_client.is_available():
            self.nodes.append(MCPNodes(mcp_client))
        self.parser = XmlToolResultParser(tools=self.get_nodes_schema())

    async def get_system_template(self, request, state = None):
        """
        Override base implementation to add coder-specific default values.
        """
        if "custom_instructions" not in request.kwargs:
            request.kwargs["custom_instructions"] = ""

        return await super().get_system_template(request)
